'    Copyright 2008 Jan Molnar <jan.molnar@abds.de>
'
'    This file is part of JCQ.

'    JCQ is free software: you can redistribute it and/or modify
'    it under the terms of the GNU General Public License as published by
'    the Free Software Foundation, either version 2 of the License, or
'    (at your option) any later version.

'    JCQ is distributed in the hope that it will be useful,
'    but WITHOUT ANY WARRANTY; without even the implied warranty of
'    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'    GNU General Public License for more details.

'    You should have received a copy of the GNU General Public License
'    along with JCQ. If not, see <http://www.gnu.org/licenses/>.

Public Class Mapper
    Implements Interfaces.IMapper

    Private _Mappings As New System.Collections.Generic.Dictionary(Of System.Type, System.Type)

    Public Sub New()
        _Mappings = New System.Collections.Generic.Dictionary(Of System.Type, System.Type)

        LoadMappings()
    End Sub

    Private Sub LoadMappings()
        Dim mkSection As JCsTools.Core.Configuration.MicrokernelSection

        mkSection = DirectCast(System.Configuration.ConfigurationManager.GetSection("Microkernel"), Core.Configuration.MicrokernelSection)

        If mkSection Is Nothing Then Throw New ConfigSectionNotFoundException("Microkernel")

        For Each element As Configuration.MappingConfigElement In mkSection.References
            Dim interfaceType As Type
            Dim mappingType As Type

            interfaceType = Type.GetType(element.InterfaceType, True, True)
            mappingType = Type.GetType(element.MappingType, True, True)

            _Mappings.Add(interfaceType, mappingType)
        Next
    End Sub

    Public Function CreateImplementation(Of I)(ByVal ParamArray args() As System.Object) As I Implements Interfaces.IMapper.CreateImplementation
        Return DirectCast(CreateImplementation(GetType(I), args), I)
    End Function

    Public Function CreateImplementation(ByVal interfaceType As System.Type, ByVal ParamArray args() As Object) As Object Implements Interfaces.IMapper.CreateImplementation
        Dim mType As System.Type

        mType = GetImplementationType(interfaceType)

        If mType Is Nothing Then Throw New Interfaces.ImplementationNotFoundException(interfaceType)

        Return System.Activator.CreateInstance(mType, args)
    End Function

    Public Function GetImplementationType(Of I)() As System.Type Implements Interfaces.IMapper.GetImplementationType
        Return GetImplementationType(GetType(I))
    End Function

    Public Function GetImplementationType(ByVal interfaceType As System.Type) As System.Type Implements Interfaces.IMapper.GetImplementationType
        Dim mappedType As System.Type = Nothing

        If interfaceType.IsInterface Then
            If Not _Mappings.ContainsKey(interfaceType) Then
                Throw New Interfaces.ImplementationNotFoundException(interfaceType)
            Else
                mappedType = _Mappings(interfaceType)
            End If
        Else
            mappedType = interfaceType
        End If

        Return mappedType
    End Function

    Public Function ExistsImplementation(Of I)() As Boolean Implements Interfaces.IMapper.ExistsImplementation
        Return ExistsImplementation(GetType(I))
    End Function

    Public Function ExistsImplementation(ByVal interfaceType As System.Type) As Boolean Implements Interfaces.IMapper.ExistsImplementation
        Return _Mappings.ContainsKey(interfaceType)
    End Function

    Public Sub AddImplementationMapping(ByVal contractType As System.Type, ByVal implementationType As System.Type) Implements Interfaces.IMapper.AddImplementationMapping
        SyncLock _Mappings
            _Mappings.Add(contractType, implementationType)
        End SyncLock
    End Sub
End Class

